<template>
  <div class="tetris-container">
    <div class="tetris-game">
      <div class="game-board-container">
        <canvas 
          ref="gameCanvas" 
          class="game-board"
          :width="canvasWidth" 
          :height="canvasHeight"
        ></canvas>
      </div>

      <div class="game-info">
        <div class="info-section">
          <div class="info-label">关卡</div>
          <div class="info-value level-value">{{ level }}</div>
        </div>

        <div class="info-section">
          <div class="info-label">分数</div>
          <div class="info-value score-value">{{ score }}</div>
        </div>

        <div class="info-section">
          <div class="info-label">下个</div>
          <div class="next-piece-preview">
            <canvas 
              ref="nextPieceCanvas" 
              class="preview-canvas"
              :width="previewCanvasSize" 
              :height="previewCanvasSize"
            ></canvas>
          </div>
          <div class="next-piece-preview">
            <canvas 
              ref="afterNextPieceCanvas" 
              class="preview-canvas"
              :width="previewCanvasSize" 
              :height="previewCanvasSize"
            ></canvas>
          </div>
        </div>

        <button class="pause-button" @click="togglePause">
          <span v-if="isPaused">▶</span>
          <span v-else>❚❚</span>
        </button>
      </div>
    </div>

    <div class="game-controls">
      <div class="direction-controls">
        <button class="control-button left-button" @click="moveLeft">◀</button>
        <button class="control-button right-button" @click="moveRight">▶</button>
        <button class="control-button down-button" @click="moveDown">▼</button>
      </div>
      <div class="action-controls">
        <button class="control-button drop-button" @click="dropPiece">▼</button>
        <button class="control-button rotate-button" @click="rotatePiece">↻</button>
      </div>
    </div>

    <!-- Game over modal -->
    <div v-if="gameOver" class="game-modal">
      <div class="modal-content">
        <h2>Game Over</h2>
        <p>Your score: {{ score }}</p>
        <button @click="restartGame">Play Again</button>
      </div>
    </div>

    <!-- Pause modal -->
    <div v-if="isPaused && !gameOver" class="game-modal">
      <div class="modal-content">
        <h2>Game Paused</h2>
        <button @click="togglePause">Resume</button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';

// Tetromino shapes and colors
const TETROMINOES = {
  I: {
    shape: [
      [0, 0, 0, 0],
      [1, 1, 1, 1],
      [0, 0, 0, 0],
      [0, 0, 0, 0],
    ],
    color: '#00bcd4', // Cyan
  },
  J: {
    shape: [
      [1, 0, 0],
      [1, 1, 1],
      [0, 0, 0],
    ],
    color: '#2196f3', // Blue
  },
  L: {
    shape: [
      [0, 0, 1],
      [1, 1, 1],
      [0, 0, 0],
    ],
    color: '#ff9800', // Orange
  },
  O: {
    shape: [
      [1, 1],
      [1, 1],
    ],
    color: '#ffeb3b', // Yellow
  },
  S: {
    shape: [
      [0, 1, 1],
      [1, 1, 0],
      [0, 0, 0],
    ],
    color: '#4caf50', // Green
  },
  T: {
    shape: [
      [0, 1, 0],
      [1, 1, 1],
      [0, 0, 0],
    ],
    color: '#9c27b0', // Purple
  },
  Z: {
    shape: [
      [1, 1, 0],
      [0, 1, 1],
      [0, 0, 0],
    ],
    color: '#f44336', // Red
  },
};

// Wall kick data (Super Rotation System)
const WALL_KICK_DATA = {
  JLSTZ: [
    [[0, 0], [-1, 0], [-1, 1], [0, -2], [-1, -2]], // 0->1
    [[0, 0], [1, 0], [1, -1], [0, 2], [1, 2]],     // 1->2
    [[0, 0], [1, 0], [1, 1], [0, -2], [1, -2]],    // 2->3
    [[0, 0], [-1, 0], [-1, -1], [0, 2], [-1, 2]]   // 3->0
  ],
  I: [
    [[0, 0], [-2, 0], [1, 0], [-2, -1], [1, 2]],   // 0->1
    [[0, 0], [-1, 0], [2, 0], [-1, 2], [2, -1]],   // 1->2
    [[0, 0], [2, 0], [-1, 0], [2, 1], [-1, -2]],   // 2->3
    [[0, 0], [1, 0], [-2, 0], [1, -2], [-2, 1]]    // 3->0
  ]
};

// Game constants
const BOARD_WIDTH = 10;
const BOARD_HEIGHT = 20;
const PREVIEW_SIZE = 4;
const ANIMATION_DURATION = 250; // ms
const CELL_SIZE = 24; // Size of each cell in pixels
const PREVIEW_CELL_SIZE = 16; // Size of each cell in preview
const GRID_LINE_WIDTH = 1; // Width of grid lines
const GRID_COLOR = '#333'; // Color of grid lines
const BG_COLOR = '#000'; // Background color

// Canvas dimensions
const canvasWidth = CELL_SIZE * BOARD_WIDTH + GRID_LINE_WIDTH;
const canvasHeight = CELL_SIZE * BOARD_HEIGHT + GRID_LINE_WIDTH;
const previewCanvasSize = PREVIEW_CELL_SIZE * PREVIEW_SIZE + GRID_LINE_WIDTH;

// Canvas references
const gameCanvas = ref(null);
const nextPieceCanvas = ref(null);
const afterNextPieceCanvas = ref(null);
let ctx = null;
let nextCtx = null;
let afterNextCtx = null;

// Animation frame ID
let animationFrameId = null;

// Animation properties
const animations = reactive({
  landingPieces: [], // Pieces that are landing
  clearingRows: [], // Rows that are being cleared
  animationStartTime: 0, // When the current animation started
});

// Game state
const board = ref(createEmptyBoard());
const currentPiece = ref(randomTetromino());
const nextPiece = ref(randomTetromino());
const afterNextPiece = ref(randomTetromino());
const score = ref(0);
const level = ref(1);
const gameOver = ref(false);
const isPaused = ref(false);
const gameLoopInterval = ref(null);
const isDropping = ref(false); // Track if piece is in rapid descent
const isSettling = ref(false); // Track piece settling state
const rotationState = ref(0); // Track current rotation state (0-3)
const isAnimating = ref(false); // Track if any animation is in progress
const clearedRows = ref([]); // Track which rows are being cleared

// Create an empty game board
function createEmptyBoard() {
  return Array.from({ length: BOARD_HEIGHT }, () => 
    Array.from({ length: BOARD_WIDTH }, () => ({ 
      filled: false, 
      color: '', 
      isGhost: false,
      isLanding: false,
      isClearing: false
    }))
  );
}

// Generate a random tetromino
function randomTetromino() {
  const keys = Object.keys(TETROMINOES);
  const tetromino = keys[Math.floor(Math.random() * keys.length)];
  return {
    pos: { x: 3, y: 0 },
    tetromino: TETROMINOES[tetromino],
    name: tetromino,
  };
}

// Check if position is valid
function isPositionValid(piece, pos) {
  for (let y = 0; y < piece.tetromino.shape.length; y++) {
    for (let x = 0; x < piece.tetromino.shape[y].length; x++) {
      // Skip empty cells
      if (!piece.tetromino.shape[y][x]) continue;

      // Check boundaries
      if (pos.y + y < 0 || pos.y + y >= BOARD_HEIGHT || pos.x + x < 0 || pos.x + x >= BOARD_WIDTH) {
        return false;
      }

      // Check collision with existing pieces
      if (board.value[pos.y + y][pos.x + x].filled) {
        return false;
      }
    }
  }
  return true;
}

// Calculate ghost piece position (projection)
function calculateGhostPosition(piece) {
  let ghostY = piece.pos.y;
  
  // Find the lowest valid position
  while (isPositionValid(piece, { x: piece.pos.x, y: ghostY + 1 })) {
    ghostY++;
  }
  
  return { x: piece.pos.x, y: ghostY };
}

// Merge the current piece with the board
function mergePieceWithBoard() {
  const newBoard = JSON.parse(JSON.stringify(board.value));
  const landingPieces = [];
  
  // Add landing animation flag to the cells where the piece lands
  for (let y = 0; y < currentPiece.value.tetromino.shape.length; y++) {
    for (let x = 0; x < currentPiece.value.tetromino.shape[y].length; x++) {
      if (currentPiece.value.tetromino.shape[y][x]) {
        const boardY = currentPiece.value.pos.y + y;
        const boardX = currentPiece.value.pos.x + x;
        if (boardY >= 0 && boardY < BOARD_HEIGHT && boardX >= 0 && boardX < BOARD_WIDTH) {
          newBoard[boardY][boardX] = {
            filled: true,
            color: currentPiece.value.tetromino.color,
            isGhost: false,
            isLanding: true,
            isClearing: false
          };
          
          // Add to landing pieces for animation
          landingPieces.push({
            x: boardX,
            y: boardY,
            color: currentPiece.value.tetromino.color
          });
        }
      }
    }
  }
  
  // Start landing animation
  animations.landingPieces = landingPieces;
  animations.animationStartTime = performance.now();
  
  return newBoard;
}

// Check for completed rows
function checkRows(boardToCheck) {
  let rowsToCheck = [];
  let rowsCleared = 0;
  
  // Find completed rows
  boardToCheck.forEach((row, index) => {
    if (row.every(cell => cell.filled)) {
      rowsToCheck.push(index);
      rowsCleared++;
    }
  });
  
  // If no rows to clear, return the board as is
  if (rowsCleared === 0) {
    return { newBoard: boardToCheck, rowsCleared: 0 };
  }
  
  // Mark rows for clearing animation
  clearedRows.value = rowsToCheck;
  const boardWithClearingRows = JSON.parse(JSON.stringify(boardToCheck));
  
  rowsToCheck.forEach(rowIndex => {
    for (let x = 0; x < BOARD_WIDTH; x++) {
      boardWithClearingRows[rowIndex][x].isClearing = true;
    }
  });
  
  // Start clearing animation
  animations.clearingRows = rowsToCheck;
  animations.animationStartTime = performance.now();
  
  // Update score based on cleared rows
  const points = [0, 40, 100, 300, 1200][rowsCleared] * level.value;
  score.value += points;
  
  return { 
    newBoard: boardWithClearingRows, 
    rowsCleared: rowsCleared 
  };
}

// Remove cleared rows and add new ones at the top
function removeRows() {
  // Create a new board without the cleared rows
  let newBoard = board.value.filter((_, index) => !clearedRows.value.includes(index));
  
  // Add new empty rows at the top
  while (newBoard.length < BOARD_HEIGHT) {
    newBoard.unshift(Array.from({ length: BOARD_WIDTH }, () => ({ 
      filled: false, 
      color: '', 
      isGhost: false,
      isLanding: false,
      isClearing: false
    })));
  }
  
  // Reset cleared rows
  clearedRows.value = [];
  animations.clearingRows = [];
  
  return newBoard;
}

// Move the current piece
function movePiece(direction) {
  if (gameOver.value || isPaused.value || isAnimating.value) return false;

  const newPos = {
    x: currentPiece.value.pos.x + direction.x,
    y: currentPiece.value.pos.y + direction.y,
  };

  if (isPositionValid(currentPiece.value, newPos)) {
    currentPiece.value.pos = newPos;
    return true;
  }

  // If moving down and position is invalid, merge piece with board
  if (direction.y > 0) {
    isSettling.value = true; // Piece is settling
    isAnimating.value = true; // Start animation sequence
    
    // Merge piece with board (with landing animation)
    const mergedBoard = mergePieceWithBoard();
    board.value = mergedBoard;
    
    // Wait for landing animation to complete
    setTimeout(() => {
      // Check for completed rows
      const { newBoard, rowsCleared } = checkRows(mergedBoard);
      board.value = newBoard;
      
      if (rowsCleared > 0) {
        // If rows were cleared, wait for clearing animation
        setTimeout(() => {
          // Remove cleared rows and add new ones
          board.value = removeRows();
          
          // Generate new piece after animations
          spawnNewPiece();
        }, ANIMATION_DURATION);
      } else {
        // No rows cleared, just spawn new piece
        // Remove landing animation
        for (let y = 0; y < BOARD_HEIGHT; y++) {
          for (let x = 0; x < BOARD_WIDTH; x++) {
            if (board.value[y][x].isLanding) {
              board.value[y][x].isLanding = false;
            }
          }
        }
        animations.landingPieces = [];
        
        // Generate new piece
        spawnNewPiece();
      }
    }, ANIMATION_DURATION);
  }

  return false;
}

// Spawn a new piece after animations
function spawnNewPiece() {
  // Generate new piece
  currentPiece.value = nextPiece.value;
  nextPiece.value = afterNextPiece.value;
  afterNextPiece.value = randomTetromino();
  rotationState.value = 0; // Reset rotation state for new piece
  
  // Update preview canvases
  drawPreviewPiece(nextPieceCanvas.value, nextPiece.value);
  drawPreviewPiece(afterNextPieceCanvas.value, afterNextPiece.value);

  // Check if game over
  if (!isPositionValid(currentPiece.value, { x: 3, y: 0 })) {
    gameOver.value = true;
    clearInterval(gameLoopInterval.value);
    cancelAnimationFrame(animationFrameId);
  }
  
  // Reset states with appropriate timing
  setTimeout(() => {
    isSettling.value = false;
    isAnimating.value = false;
  }, ANIMATION_DURATION / 2);
}

// Move functions for controls
function moveLeft() {
  movePiece({ x: -1, y: 0 });
}

function moveRight() {
  movePiece({ x: 1, y: 0 });
}

function moveDown() {
  movePiece({ x: 0, y: 1 });
}

// Rotate the current piece with wall kicks
function rotatePiece() {
  if (gameOver.value || isPaused.value || isAnimating.value) return;

  // O piece doesn't need rotation
  if (currentPiece.value.name === 'O') return;

  const rotatedShape = currentPiece.value.tetromino.shape[0].map((_, index) =>
    currentPiece.value.tetromino.shape.map(row => row[index]).reverse()
  );

  const rotatedPiece = {
    ...currentPiece.value,
    tetromino: {
      ...currentPiece.value.tetromino,
      shape: rotatedShape,
    },
  };

  // Determine which wall kick data to use
  const kickData = currentPiece.value.name === 'I' 
    ? WALL_KICK_DATA.I[rotationState.value] 
    : WALL_KICK_DATA.JLSTZ[rotationState.value];

  // Try each possible position
  for (const [offsetX, offsetY] of kickData) {
    const newPos = {
      x: currentPiece.value.pos.x + offsetX,
      y: currentPiece.value.pos.y - offsetY // Y is inverted in our coordinate system
    };
    
    if (isPositionValid(rotatedPiece, newPos)) {
      currentPiece.value = rotatedPiece;
      currentPiece.value.pos = newPos;
      
      // Update rotation state (0-3)
      rotationState.value = (rotationState.value + 1) % 4;
      
      return; // Successfully rotated
    }
  }
  
  // If we get here, no valid rotation was found
}

// Drop the piece all the way down
function dropPiece() {
  if (gameOver.value || isPaused.value || isAnimating.value) return;

  isDropping.value = true; // Start dropping - hide ghost piece

  let newY = currentPiece.value.pos.y;
  while (isPositionValid(currentPiece.value, { x: currentPiece.value.pos.x, y: newY + 1 })) {
    newY++;
  }

  currentPiece.value.pos.y = newY;
  isSettling.value = true; // Piece is settling
  isAnimating.value = true; // Start animation sequence
  
  // Merge piece with board (with landing animation)
  const mergedBoard = mergePieceWithBoard();
  board.value = mergedBoard;
  
  // Wait for landing animation to complete
  setTimeout(() => {
    // Check for completed rows
    const { newBoard, rowsCleared } = checkRows(mergedBoard);
    board.value = newBoard;
    
    if (rowsCleared > 0) {
      // If rows were cleared, wait for clearing animation
      setTimeout(() => {
        // Remove cleared rows and add new ones
        board.value = removeRows();
        
        // Reset dropping state
        isDropping.value = false;
        
        // Generate new piece after animations
        spawnNewPiece();
      }, ANIMATION_DURATION);
    } else {
      // No rows cleared, just spawn new piece
      // Remove landing animation
      for (let y = 0; y < BOARD_HEIGHT; y++) {
        for (let x = 0; x < BOARD_WIDTH; x++) {
          if (board.value[y][x].isLanding) {
            board.value[y][x].isLanding = false;
          }
        }
      }
      animations.landingPieces = [];
      
      // Reset dropping state
      isDropping.value = false;
      
      // Generate new piece
      spawnNewPiece();
    }
  }, ANIMATION_DURATION);
  
  // Reset the game loop to prevent immediate additional movement
  clearInterval(gameLoopInterval.value);
  startGameLoop();
}

// Toggle pause state
function togglePause() {
  isPaused.value = !isPaused.value;
  if (isPaused.value) {
    clearInterval(gameLoopInterval.value);
    cancelAnimationFrame(animationFrameId);
  } else {
    startGameLoop();
    requestAnimationFrame(renderGame);
  }
}

// Restart the game
function restartGame() {
  board.value = createEmptyBoard();
  currentPiece.value = randomTetromino();
  nextPiece.value = randomTetromino();
  afterNextPiece.value = randomTetromino();
  score.value = 0;
  level.value = 1;
  gameOver.value = false;
  isPaused.value = false;
  isDropping.value = false;
  isSettling.value = false;
  isAnimating.value = false;
  clearedRows.value = [];
  animations.landingPieces = [];
  animations.clearingRows = [];
  rotationState.value = 0;
  
  // Update preview canvases
  drawPreviewPiece(nextPieceCanvas.value, nextPiece.value);
  drawPreviewPiece(afterNextPieceCanvas.value, afterNextPiece.value);
  
  startGameLoop();
  requestAnimationFrame(renderGame);
}

// Start the game loop
function startGameLoop() {
  if (gameLoopInterval.value) {
    clearInterval(gameLoopInterval.value);
  }
  
  const speed = Math.max(100, 1000 - (level.value - 1) * 100);
  gameLoopInterval.value = setInterval(() => {
    if (!isAnimating.value) {
      movePiece({ x: 0, y: 1 });
    }
  }, speed);
}

// Handle keyboard controls
function handleKeyDown(e) {
  if (gameOver.value) return;

  switch (e.key) {
    case 'ArrowLeft':
      moveLeft();
      break;
    case 'ArrowRight':
      moveRight();
      break;
    case 'ArrowDown':
      moveDown();
      break;
    case 'ArrowUp':
      rotatePiece();
      break;
    case ' ':
      dropPiece();
      break;
    case 'p':
      togglePause();
      break;
    default:
      break;
  }
}

// Draw a single cell on the canvas
function drawCell(ctx, x, y, color, size, isGhost = false) {
  const xPos = x * size;
  const yPos = y * size;
  
  if (isGhost) {
    // Draw ghost piece
    ctx.strokeStyle = color;
    ctx.lineWidth = 2;
    ctx.strokeRect(xPos + 3, yPos + 3, size - 6, size - 6);
    
    // Add a subtle fill
    ctx.fillStyle = color + '33'; // 20% opacity
    ctx.fillRect(xPos + 3, yPos + 3, size - 6, size - 6);
  } else {
    // Draw filled cell
    ctx.fillStyle = color;
    ctx.fillRect(xPos + 1, yPos + 1, size - 2, size - 2);
    
    // Add 3D effect
    ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
    ctx.beginPath();
    ctx.moveTo(xPos + 1, yPos + 1);
    ctx.lineTo(xPos + size - 1, yPos + 1);
    ctx.lineTo(xPos + size - 1, yPos + size - 1);
    ctx.lineTo(xPos + 1, yPos + size - 1);
    ctx.closePath();
    ctx.fill();
  }
}

// Draw the game board grid
function drawGrid(ctx, width, height, cellSize) {
  ctx.strokeStyle = GRID_COLOR;
  ctx.lineWidth = GRID_LINE_WIDTH;
  
  // Draw vertical lines
  for (let x = 0; x <= width; x++) {
    ctx.beginPath();
    ctx.moveTo(x * cellSize, 0);
    ctx.lineTo(x * cellSize, height * cellSize);
    ctx.stroke();
  }
  
  // Draw horizontal lines
  for (let y = 0; y <= height; y++) {
    ctx.beginPath();
    ctx.moveTo(0, y * cellSize);
    ctx.lineTo(width * cellSize, y * cellSize);
    ctx.stroke();
  }
}

// Draw the current game state
function drawBoard() {
  // Clear the canvas
  ctx.fillStyle = BG_COLOR;
  ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  
  // Draw the grid
  drawGrid(ctx, BOARD_WIDTH, BOARD_HEIGHT, CELL_SIZE);
  
  // Draw the board cells
  for (let y = 0; y < BOARD_HEIGHT; y++) {
    for (let x = 0; x < BOARD_WIDTH; x++) {
      const cell = board.value[y][x];
      if (cell.filled) {
        drawCell(ctx, x, y, cell.color, CELL_SIZE);
      }
    }
  }
  
  // Draw ghost piece if not dropping or settling
  if (!isDropping.value && !isSettling.value && !isAnimating.value) {
    const ghostPos = calculateGhostPosition(currentPiece.value);
    
    for (let y = 0; y < currentPiece.value.tetromino.shape.length; y++) {
      for (let x = 0; x < currentPiece.value.tetromino.shape[y].length; x++) {
        if (currentPiece.value.tetromino.shape[y][x]) {
          const boardY = ghostPos.y + y;
          const boardX = ghostPos.x + x;
          
          // Only draw ghost if it's not where the actual piece is
          if (boardY >= 0 && boardY < BOARD_HEIGHT && boardX >= 0 && boardX < BOARD_WIDTH &&
              (boardY !== currentPiece.value.pos.y + y || boardX !== currentPiece.value.pos.x + x)) {
            // Don't draw ghost over existing filled cells
            if (!board.value[boardY][boardX].filled) {
              drawCell(ctx, boardX, boardY, currentPiece.value.tetromino.color, CELL_SIZE, true);
            }
          }
        }
      }
    }
  }
  
  // Draw current piece if not animating
  if (!isAnimating.value) {
    for (let y = 0; y < currentPiece.value.tetromino.shape.length; y++) {
      for (let x = 0; x < currentPiece.value.tetromino.shape[y].length; x++) {
        if (currentPiece.value.tetromino.shape[y][x]) {
          const boardY = currentPiece.value.pos.y + y;
          const boardX = currentPiece.value.pos.x + x;
          if (boardY >= 0 && boardY < BOARD_HEIGHT && boardX >= 0 && boardX < BOARD_WIDTH) {
            drawCell(ctx, boardX, boardY, currentPiece.value.tetromino.color, CELL_SIZE);
          }
        }
      }
    }
  }
}

// Draw a preview piece on a canvas
function drawPreviewPiece(canvas, piece) {
  if (!canvas) return;
  
  const previewCtx = canvas.getContext('2d');
  
  // Clear the canvas
  previewCtx.fillStyle = '#3e2723'; // Preview background color
  previewCtx.fillRect(0, 0, previewCanvasSize, previewCanvasSize);
  
  // Draw grid
  drawGrid(previewCtx, PREVIEW_SIZE, PREVIEW_SIZE, PREVIEW_CELL_SIZE);
  
  // Get the shape
  const shape = piece.tetromino.shape;
  
  // Calculate the actual dimensions of the piece
  let minX = shape[0].length;
  let minY = shape.length;
  let maxX = 0;
  let maxY = 0;
  
  for (let y = 0; y < shape.length; y++) {
    for (let x = 0; x < shape[y].length; x++) {
      if (shape[y][x]) {
        minX = Math.min(minX, x);
        minY = Math.min(minY, y);
        maxX = Math.max(maxX, x);
        maxY = Math.max(maxY, y);
      }
    }
  }
  
  const pieceWidth = maxX - minX + 1;
  const pieceHeight = maxY - minY + 1;
  
  // Calculate centering offsets
  const offsetX = Math.floor((PREVIEW_SIZE - pieceWidth) / 2);
  const offsetY = Math.floor((PREVIEW_SIZE - pieceHeight) / 2);
  
  // Draw the piece centered
  for (let y = minY; y <= maxY; y++) {
    for (let x = minX; x <= maxX; x++) {
      if (shape[y][x]) {
        drawCell(
          previewCtx, 
          x - minX + offsetX, 
          y - minY + offsetY, 
          piece.tetromino.color, 
          PREVIEW_CELL_SIZE
        );
      }
    }
  }
}

// Draw animations
function drawAnimations(timestamp) {
  const elapsed = timestamp - animations.animationStartTime;
  const progress = Math.min(elapsed / ANIMATION_DURATION, 1);
  
  // Draw landing animation
  if (animations.landingPieces.length > 0) {
    for (const piece of animations.landingPieces) {
      const scale = 1 + 0.2 * Math.sin(progress * Math.PI); // Scale up and back down
      const brightness = 1 + 0.5 * Math.sin(progress * Math.PI); // Brighten and back to normal
      
      // Apply scale and brightness
      ctx.save();
      ctx.translate(piece.x * CELL_SIZE + CELL_SIZE / 2, piece.y * CELL_SIZE + CELL_SIZE / 2);
      ctx.scale(scale, scale);
      
      // Adjust color brightness
      const color = piece.color;
      ctx.fillStyle = adjustBrightness(color, brightness);
      ctx.fillRect(-CELL_SIZE / 2 + 1, -CELL_SIZE / 2 + 1, CELL_SIZE - 2, CELL_SIZE - 2);
      
      // Add 3D effect
      ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
      ctx.beginPath();
      ctx.moveTo(-CELL_SIZE / 2 + 1, -CELL_SIZE / 2 + 1);
      ctx.lineTo(CELL_SIZE / 2 - 1, -CELL_SIZE / 2 + 1);
      ctx.lineTo(CELL_SIZE / 2 - 1, CELL_SIZE / 2 - 1);
      ctx.lineTo(-CELL_SIZE / 2 + 1, CELL_SIZE / 2 - 1);
      ctx.closePath();
      ctx.fill();
      
      ctx.restore();
    }
  }
  
  // Draw clearing animation
  if (animations.clearingRows.length > 0) {
    for (const rowIndex of animations.clearingRows) {
      for (let x = 0; x < BOARD_WIDTH; x++) {
        const cell = board.value[rowIndex][x];
        if (cell.filled && cell.isClearing) {
          const scale = 1 - progress; // Shrink to nothing
          const brightness = 1 + progress; // Get brighter
          
          // Apply scale and brightness
          ctx.save();
          ctx.translate(x * CELL_SIZE + CELL_SIZE / 2, rowIndex * CELL_SIZE + CELL_SIZE / 2);
          ctx.scale(scale, scale);
          
          // Adjust color brightness and add white glow as it disappears
          const color = cell.color;
          const mixRatio = progress;
          ctx.fillStyle = mixColors(color, '#FFFFFF', mixRatio);
          ctx.fillRect(-CELL_SIZE / 2 + 1, -CELL_SIZE / 2 + 1, CELL_SIZE - 2, CELL_SIZE - 2);
          
          ctx.restore();
        }
      }
    }
  }
}

// Adjust color brightness
function adjustBrightness(color, factor) {
  // Convert hex to RGB
  let r = parseInt(color.slice(1, 3), 16);
  let g = parseInt(color.slice(3, 5), 16);
  let b = parseInt(color.slice(5, 7), 16);
  
  // Adjust brightness
  r = Math.min(255, Math.round(r * factor));
  g = Math.min(255, Math.round(g * factor));
  b = Math.min(255, Math.round(b * factor));
  
  // Convert back to hex
  return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}

// Mix two colors
function mixColors(color1, color2, ratio) {
  // Convert hex to RGB
  let r1 = parseInt(color1.slice(1, 3), 16);
  let g1 = parseInt(color1.slice(3, 5), 16);
  let b1 = parseInt(color1.slice(5, 7), 16);
  
  let r2 = parseInt(color2.slice(1, 3), 16);
  let g2 = parseInt(color2.slice(3, 5), 16);
  let b2 = parseInt(color2.slice(5, 7), 16);
  
  // Mix colors
  let r = Math.round(r1 * (1 - ratio) + r2 * ratio);
  let g = Math.round(g1 * (1 - ratio) + g2 * ratio);
  let b = Math.round(b1 * (1 - ratio) + b2 * ratio);
  
  // Convert back to hex
  return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}

// Main render function
function renderGame(timestamp) {
  if (gameOver.value || isPaused.value) return;
  
  drawBoard();
  drawAnimations(timestamp);
  
  animationFrameId = requestAnimationFrame(renderGame);
}

// Update level based on score
watch(score, (newScore) => {
  const newLevel = Math.floor(newScore / 500) + 1;
  if (newLevel !== level.value) {
    level.value = newLevel;
    // Update game speed when level changes
    if (!isPaused.value && !gameOver.value) {
      startGameLoop();
    }
  }
});

// Initialize canvas and start game
onMounted(() => {
  // Get canvas contexts
  ctx = gameCanvas.value.getContext('2d');
  nextCtx = nextPieceCanvas.value.getContext('2d');
  afterNextCtx = afterNextPieceCanvas.value.getContext('2d');
  
  // Handle high DPI displays for main canvas
  const dpr = window.devicePixelRatio || 1;
  const rect = gameCanvas.value.getBoundingClientRect();
  
  gameCanvas.value.width = rect.width * dpr;
  gameCanvas.value.height = rect.height * dpr;
  
  ctx.scale(dpr, dpr);
  gameCanvas.value.style.width = `${rect.width}px`;
  gameCanvas.value.style.height = `${rect.height}px`;
  
  // Handle high DPI for preview canvases
  const previewRect = nextPieceCanvas.value.getBoundingClientRect();
  
  nextPieceCanvas.value.width = previewRect.width * dpr;
  nextPieceCanvas.value.height = previewRect.height * dpr;
  nextCtx.scale(dpr, dpr);
  nextPieceCanvas.value.style.width = `${previewRect.width}px`;
  nextPieceCanvas.value.style.height = `${previewRect.height}px`;
  
  afterNextPieceCanvas.value.width = previewRect.width * dpr;
  afterNextPieceCanvas.value.height = previewRect.height * dpr;
  afterNextCtx.scale(dpr, dpr);
  afterNextPieceCanvas.value.style.width = `${previewRect.width}px`;
  afterNextPieceCanvas.value.style.height = `${previewRect.height}px`;
  
  // Draw initial preview pieces
  drawPreviewPiece(nextPieceCanvas.value, nextPiece.value);
  drawPreviewPiece(afterNextPieceCanvas.value, afterNextPiece.value);
  
  // Add event listeners
  window.addEventListener('keydown', handleKeyDown);
  
  // Start game loop
  startGameLoop();
  
  // Start render loop
  animationFrameId = requestAnimationFrame(renderGame);
});

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown);
  if (gameLoopInterval.value) {
    clearInterval(gameLoopInterval.value);
  }
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }
});
</script>

<style scoped>
.tetris-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #f5a623;
  border-radius: 0.5rem;
  padding: 1rem;
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
  max-width: 500px;
  margin: 0 auto;
}

.tetris-game {
  display: flex;
  gap: 0.5rem;
}

.game-board-container {
  border: 4px solid #d68c16;
  background-color: black;
  padding: 0.25rem;
}

.game-board {
  display: block;
  background-color: black;
}

.game-info {
  width: 8rem;
  background-color: #2d1e19;
  color: #f5d742;
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.info-section {
  text-align: center;
  margin-bottom: 1rem;
}

.info-label {
  font-size: 1.25rem;
  margin-bottom: 0.25rem;
}

.info-value {
  background-color: black;
  color: white;
  padding: 0.25rem;
  text-align: center;
  font-size: 1.25rem;
}

.level-value {
  background-color: black;
}

.target-value {
  background-color: #8bc34a;
  height: 1.5rem;
}

.score-value {
  background-color: #f5a623;
  border-radius: 9999px;
  border: 2px solid #d68c16;
}

.next-piece-preview {
  background-color: #3e2723;
  padding: 0.5rem;
  margin-bottom: 0.5rem;
  display: flex;
  justify-content: center;
  align-items: center;
}

.preview-canvas {
  display: block;
}

.hold-info {
  background-color: #3e2723;
  padding: 0.5rem;
  text-align: center;
  font-size: 0.75rem;
}

.pause-button {
  width: 100%;
  background-color: #d32f2f;
  color: white;
  border: none;
  border-radius: 9999px;
  padding: 0.5rem;
  font-size: 1.25rem;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3), inset 0 -4px 0 rgba(0, 0, 0, 0.2);
  transition: all 0.1s ease;
}

.pause-button:hover {
  background-color: #e33e3e;
  transform: translateY(-2px);
  box-shadow: 0 6px 8px rgba(0, 0, 0, 0.3), inset 0 -4px 0 rgba(0, 0, 0, 0.2);
}

.pause-button:active {
  transform: translateY(2px);
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.3), inset 0 -2px 0 rgba(0, 0, 0, 0.2);
  background-color: #b71c1c;
}

.game-controls {
  display: flex;
  justify-content: space-between;
  width: 100%;
  margin-top: 1rem;
}

.direction-controls, .action-controls {
  display: flex;
  gap: 0.5rem;
}

.control-button {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 9999px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5rem;
  cursor: pointer;
  border: 4px solid;
  transition: all 0.1s ease;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3), inset 0 -4px 0 rgba(0, 0, 0, 0.2);
}

.control-button:active {
  transform: translateY(4px);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), inset 0 -2px 0 rgba(0, 0, 0, 0.2);
}

.left-button, .right-button, .down-button {
  background-color: #f5d742;
  border-color: #d6b93d;
  color: #8f7b1d;
}

.left-button:hover, .right-button:hover, .down-button:hover {
  background-color: #f7de5c;
  transform: translateY(-2px);
  box-shadow: 0 6px 10px rgba(0, 0, 0, 0.3), inset 0 -4px 0 rgba(0, 0, 0, 0.2);
}

.left-button:active, .right-button:active, .down-button:active {
  background-color: #e6c414;
  transform: translateY(4px);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), inset 0 -2px 0 rgba(0, 0, 0, 0.2);
}

.drop-button, .rotate-button {
  background-color: #4caf50;
  border-color: #388e3c;
  color: #1b5e20;
}

.drop-button:hover, .rotate-button:hover {
  background-color: #5cb860;
  transform: translateY(-2px);
  box-shadow: 0 6px 10px rgba(0, 0, 0, 0.3), inset 0 -4px 0 rgba(0, 0, 0, 0.2);
}

.drop-button:active, .rotate-button:active {
  background-color: #3d8b40;
  transform: translateY(4px);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), inset 0 -2px 0 rgba(0, 0, 0, 0.2);
}

.game-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background-color: white;
  padding: 1.5rem;
  border-radius: 0.5rem;
  text-align: center;
}

.modal-content h2 {
  font-size: 1.5rem;
  font-weight: bold;
  margin-bottom: 1rem;
}

.modal-content button {
  background-color: #4caf50;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
  cursor: pointer;
  font-size: 1rem;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), inset 0 -2px 0 rgba(0, 0, 0, 0.1);
  transition: all 0.1s ease;
}

.modal-content button:hover {
  background-color: #5cb860;
  transform: translateY(-1px);
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2), inset 0 -2px 0 rgba(0, 0, 0, 0.1);
}

.modal-content button:active {
  background-color: #3d8b40;
  transform: translateY(1px);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
}
</style>